﻿using System;
using System.Collections.Generic;

namespace Core
{
    // ReSharper disable once InconsistentNaming
    public class DFSGraph<T>
    {
        private readonly List<T> mData = new();
        private readonly List<List<int>> mGraph = new();

        private readonly List<int> mVisited = new();

        public void Link(T src, T tgt)
        {
            var idx1 = mData.IndexOf(src);
            if (idx1 == -1)
            {
                idx1 = mData.Count;
                mData.Add(src);
                mGraph.Add(new List<int>());
            }

            var idx2 = mData.IndexOf(tgt);
            if (idx2 == -1)
            {
                idx2 = mData.Count;
                mData.Add(src);
                mGraph.Add(new List<int>());
            }

            var links = mGraph[idx1];
            if (links.Contains(idx2) == false)
            {
                links.Add(idx2);
            }
        }

        private Action<T> mFunc;

        public void Traverse(Action<T> func)
        {
            if (func == null)
            {
                return;
            }

            mFunc = func;

            mVisited.Clear();

            for (int i = 0; i < mGraph.Count; i++)
            {
                if (mVisited.Contains(i)) continue;

                DFS(i);
            }
        }

        // ReSharper disable once InconsistentNaming
        private void DFS(int idx)
        {
            mFunc(mData[idx]);

            mVisited.Add(idx);

            var links = mGraph[idx];

            for (var i = 0; i < links.Count; i++)
            {
                var ii = links[i];

                if (mVisited.Contains(ii)) continue;

                DFS(ii);
            }
        }
    }
}
